/**
 * Project Reactor
 */


#include "SocketIO.h"
#include <sys/socket.h>
#include <stdio.h>
#include <errno.h>

/**
 * SocketIO implementation
 */
SocketIO::SocketIO(int fd)
:_fd(fd)
{

}

/**
 * @param buff
 * @param len
 * @return int
 */
int SocketIO::readn(char * buff, int len) {
int left = len;
	char * p = buff;
    //提问：left的值有可能小于0吗？不可能小于0，退出循环时，left等于0
	while(left > 0) {
		int ret = ::recv(_fd, p, left, 0);
		if(ret == -1 && errno == EINTR)
			continue;
		else if(ret == -1) {
			perror("read");
			return len - left;
		}
		else if(ret == 0) {//连接断开
			return len - left;
		} else {
			left -= ret;
			p += ret;
		}
	}
	return len - left;    
}

/**
 * @param buff
 * @param len
 * @return int
 */
int SocketIO::readline(char * buff, int maxlen) {
    int left = maxlen - 1;
	char * p = buff;
	int ret;
	int total = 0;
	while(left > 0) {
		ret = recvPeek(p, left);
		//查找 '\n'
		for(int idx = 0; idx != ret; ++idx) {
			if(p[idx] == '\n') {
				int sz = idx + 1;
				readn(p, sz);//从内核缓冲区中移走
				total += sz;
				p += sz;
				*p = '\0';
				return total;
			}
		}
		//如果没有发现 '\n'
		readn(p, ret);
		left -= ret;
		p += ret;
		total += ret;
	}
	*p = '\0';// 最终没有发现'\n'
	return total;
}

/**
 * @param buff
 * @param len
 * @return int
 */
int SocketIO::recvPeek(char* buff, int len) {
    int ret;
	do {
		ret = ::recv(_fd, buff, len, MSG_PEEK);
	} while(ret == -1 && errno == EINTR);
	return ret;
}

int SocketIO::recvPeek() {
    int ret;
    char buf[20] = {0};
	do {
		ret = ::recv(_fd, buf, sizeof(buf), MSG_PEEK);
	} while(ret == -1 && errno == EINTR);
	return ret;
}


int SocketIO::sendn(const char * buff, int len)
{
    int left = len;
	const char * p = buff;
	while(left > 0) {
		int ret = ::send(_fd, p, left, 0);
		if(ret == -1 && errno == EINTR)
			continue;
		else if(ret == -1) {
			perror("write");
			return len - left;
		} else {
			left -= ret;
			p += ret;
		}
	}
	return len - left;

}
